linq.js 是一个开源的包,我下载自 https://github.com/mihaifm/linq,大家如果需要可由此地下载,其代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /*--------------------------------------------------------------------------
2 * linq.js - LINQ for JavaScript
3 * licensed under MIT License
4 *------------------------------------------------------------------------*/
5
6 (function (root, undefined) {
7 // ReadOnly Function
8 var Functions = {
9 Identity: function (x) { return x; },
10 True: function () { return true; },
11 Blank: function () { }
12 };
13
14 // const Type
15 var Types = {
16 Boolean: typeof true,
17 Number: typeof 0,
18 String: typeof "",
19 Object: typeof {},
20 Undefined: typeof undefined,
21 Function: typeof function () { }
22 };
23
24 // createLambda cache
25 var funcCache = { "": Functions.Identity };
26
27 // private utility methods
28 var Utils = {
29 // Create anonymous function from lambda expression string
30 createLambda: function (expression) {
31 if (expression == null) return Functions.Identity;
32 if (typeof expression === Types.String) {
33 // get from cache
34 var f = funcCache[expression];
35 if (f != null) {
36 return f;
37 }
38
39 if (expression.indexOf("=>") === -1) {
40 var regexp = new RegExp("[$]+", "g");
41
42 var maxLength = 0;
43 var match;
44 while ((match = regexp.exec(expression)) != null) {
45 var paramNumber = match[0].length;
46 if (paramNumber > maxLength) {
47 maxLength = paramNumber;
48 }
49 }
50
51 var argArray = [];
52 for (var i = 1; i (.*)/);
68 f = new Function(expr[1], (expr[2].match(/\breturn\b/) ? expr[2] : "return " + expr[2]));
69 funcCache[expression] = f;
70 return f;
71 }
72 }
73 return expression;
74 },
75
76 isIEnumerable: function (obj) {
77 if (typeof Enumerator !== Types.Undefined) {
78 try {
79 new Enumerator(obj); // check JScript(IE)'s Enumerator
80 return true;
81 }
82 catch (e) { }
83 }
84
85 return false;
86 },
87
88 // IE8's defineProperty is defined but cannot use, therefore check defineProperties
89 defineProperty: (Object.defineProperties != null)
90 ? function (target, methodName, value) {
91 Object.defineProperty(target, methodName, {
92 enumerable: false,
93 configurable: true,
94 writable: true,
95 value: value
96 })
97 }
98 : function (target, methodName, value) {
99 target[methodName] = value;
100 },
101
102 compare: function (a, b) {
103 return (a === b) ? 0
104 : (a > b) ? 1
105 : -1;
106 },
107
108 dispose: function (obj) {
109 if (obj != null) obj.dispose();
110 },
111
112 hasNativeIteratorSupport: function () {
113 return typeof Symbol !== 'undefined' && typeof Symbol.iterator !== 'undefined';
114 }
115 };
116
117 // IEnumerator State
118 var State = { Before: 0, Running: 1, After: 2 };
119
120 // "Enumerator" is conflict JScript's "Enumerator"
121 var IEnumerator = function (initialize, tryGetNext, dispose) {
122 var yielder = new Yielder();
123 var state = State.Before;
124
125 this.current = yielder.current;
126
127 this.moveNext = function () {
128 try {
129 switch (state) {
130 case State.Before:
131 state = State.Running;
132 initialize();
133 // fall through
134 case State.Running:
135 if (tryGetNext.apply(yielder)) {
136 return true;
137 }
138 else {
139 this.dispose();
140 return false;
141 }
142 case State.After:
143 return false;
144 }
145 }
146 catch (e) {
147 this.dispose();
148 throw e;
149 }
150 };
151
152 this.dispose = function () {
153 if (state != State.Running) return;
154
155 try {
156 dispose();
157 }
158 finally {
159 state = State.After;
160 }
161 };
162 };
163
164 // for tryGetNext
165 var Yielder = function () {
166 var current = null;
167 this.current = function () { return current; };
168 this.yieldReturn = function (value) {
169 current = value;
170 return true;
171 };
172 this.yieldBreak = function () {
173 return false;
174 };
175 };
176
177 // Enumerable constuctor
178 var Enumerable = function (getEnumerator) {
179 this.getEnumerator = getEnumerator;
180 };
181
182 // Utility
183
184 Enumerable.Utils = {}; // container
185
186 Enumerable.Utils.createLambda = function (expression) {
187 return Utils.createLambda(expression);
188 };
189
190 Enumerable.Utils.createEnumerable = function (getEnumerator) {
191 return new Enumerable(getEnumerator);
192 };
193
194 Enumerable.Utils.createEnumerator = function (initialize, tryGetNext, dispose) {
195 return new IEnumerator(initialize, tryGetNext, dispose);
196 };
197
198 Enumerable.Utils.extendTo = function (type) {
199 var typeProto = type.prototype;
200 var enumerableProto;
201
202 if (type === Array) {
203 enumerableProto = ArrayEnumerable.prototype;
204 Utils.defineProperty(typeProto, "getSource", function () {
205 return this;
206 });
207 }
208 else {
209 enumerableProto = Enumerable.prototype;
210 Utils.defineProperty(typeProto, "getEnumerator", function () {
211 return Enumerable.from(this).getEnumerator();
212 });
213 }
214
215 for (var methodName in enumerableProto) {
216 var func = enumerableProto[methodName];
217
218 // already extended
219 if (typeProto[methodName] == func) continue;
220
221 // already defined(example Array#reverse/join/forEach...)
222 if (typeProto[methodName] != null) {
223 methodName = methodName + "ByLinq";
224 if (typeProto[methodName] == func) continue; // recheck
225 }
226
227 if (func instanceof Function) {
228 Utils.defineProperty(typeProto, methodName, func);
229 }
230 }
231 };
232
233 Enumerable.Utils.recallFrom = function (type) {
234 var typeProto = type.prototype;
235 var enumerableProto;
236
237 if (type === Array) {
238 enumerableProto = ArrayEnumerable.prototype;
239 delete typeProto.getSource;
240 }
241 else {
242 enumerableProto = Enumerable.prototype;
243 delete typeProto.getEnumerator;
244 }
245
246 for (var methodName in enumerableProto) {
247 var func = enumerableProto[methodName];
248
249 if (typeProto[methodName + 'ByLinq']) {
250 delete typeProto[methodName + 'ByLinq'];
251 }
252 else if (typeProto[methodName] == func && func instanceof Function) {
253 delete typeProto[methodName];
254 }
255 }
256 };
257
258 // Generator
259
260 Enumerable.choice = function () // variable argument
261 {
262 var args = arguments;
263
264 return new Enumerable(function () {
265 return new IEnumerator(
266 function () {
267 args = (args[0] instanceof Array) ? args[0]
268 : (args[0].getEnumerator != null) ? args[0].toArray()
269 : args;
270 },
271 function () {
272 return this.yieldReturn(args[Math.floor(Math.random() * args.length)]);
273 },
274 Functions.Blank);
275 });
276 };
277
278 Enumerable.cycle = function () // variable argument
279 {
280 var args = arguments;
281
282 return new Enumerable(function () {
283 var index = 0;
284 return new IEnumerator(
285 function () {
286 args = (args[0] instanceof Array) ? args[0]
287 : (args[0].getEnumerator != null) ? args[0].toArray()
288 : args;
289 },
290 function () {
291 if (index >= args.length) index = 0;
292 return this.yieldReturn(args[index++]);
293 },
294 Functions.Blank);
295 });
296 };
297
298 Enumerable.empty = function () {
299 return new Enumerable(function () {
300 return new IEnumerator(
301 Functions.Blank,
302 function () { return false; },
303 Functions.Blank);
304 });
305 };
306
307 Enumerable.from = function (obj) {
308 if (obj == null) {
309 return Enumerable.empty();
310 }
311 if (obj instanceof Enumerable) {
312 return obj;
313 }
314 if (typeof obj == Types.Number || typeof obj == Types.Boolean) {
315 return Enumerable.repeat(obj, 1);
316 }
317 if (typeof obj == Types.String) {
318 return new Enumerable(function () {
319 var index = 0;
320 return new IEnumerator(
321 Functions.Blank,
322 function () {
323 return (index < obj.length) ? this.yieldReturn(obj.charAt(index++)) : false;
324 },
325 Functions.Blank);
326 });
327 }
328 if (typeof obj != Types.Function) {
329 // array or array like object
330 if (typeof obj.length == Types.Number) {
331 return new ArrayEnumerable(obj);
332 }
333
334 // iterable object
335 if (typeof Symbol !== 'undefined' && typeof obj[Symbol.iterator] !== 'undefined') {
336 return new Enumerable(function () {
337 return new IEnumerator(
338 Functions.Blank,
339 function () {
340 var next = obj.next();
341 return (next.done ? false : (this.yieldReturn(next.value)));
342 },
343 Functions.Blank);
344 });
345 }
346
347 // JScript's IEnumerable
348 if (!(obj instanceof Object) && Utils.isIEnumerable(obj)) {
349 return new Enumerable(function () {
350 var isFirst = true;
351 var enumerator;
352 return new IEnumerator(
353 function () { enumerator = new Enumerator(obj); },
354 function () {
355 if (isFirst) isFirst = false;
356 else enumerator.moveNext();
357
358 return (enumerator.atEnd()) ? false : this.yieldReturn(enumerator.item());
359 },
360 Functions.Blank);
361 });
362 }
363
364 // WinMD IIterable
365 if (typeof Windows === Types.Object && typeof obj.first === Types.Function) {
366 return new Enumerable(function () {
367 var isFirst = true;
368 var enumerator;
369 return new IEnumerator(
370 function () { enumerator = obj.first(); },
371 function () {
372 if (isFirst) isFirst = false;
373 else enumerator.moveNext();
374
375 return (enumerator.hasCurrent) ? this.yieldReturn(enumerator.current) : this.yieldBreak();
376 },
377 Functions.Blank);
378 });
379 }
380 }
381
382 // case function/object : Create keyValuePair[]
383 return new Enumerable(function () {
384 var array = [];
385 var index = 0;
386
387 return new IEnumerator(
388 function () {
389 for (var key in obj) {
390 var value = obj[key];
391 if (!(value instanceof Function) && Object.prototype.hasOwnProperty.call(obj, key)) {
392 array.push({ key: key, value: value });
393 }
394 }
395 },
396 function () {
397 return (index = draw) {
1646 upper = index;
1647 }
1648 else {
1649 lower = index;
1650 }
1651 }
1652
1653 return this.yieldReturn(sortedByBound[upper].value);
1654 }
1655
1656 return this.yieldBreak();
1657 },
1658 Functions.Blank);
1659 });
1660 };
1661
1662 /* Grouping Methods */
1663
1664 // Overload:function(keySelector)
1665 // Overload:function(keySelector,elementSelector)
1666 // Overload:function(keySelector,elementSelector,resultSelector)
1667 // Overload:function(keySelector,elementSelector,resultSelector,compareSelector)
1668 Enumerable.prototype.groupBy = function (keySelector, elementSelector, resultSelector, compareSelector) {
1669 var source = this;
1670 keySelector = Utils.createLambda(keySelector);
1671 elementSelector = Utils.createLambda(elementSelector);
1672 if (resultSelector != null) resultSelector = Utils.createLambda(resultSelector);
1673 compareSelector = Utils.createLambda(compareSelector);
1674
1675 return new Enumerable(function () {
1676 var enumerator;
1677
1678 return new IEnumerator(
1679 function () {
1680 enumerator = source.toLookup(keySelector, elementSelector, compareSelector)
1681 .toEnumerable()
1682 .getEnumerator();
1683 },
1684 function () {
1685 while (enumerator.moveNext()) {
1686 return (resultSelector == null)
1687 ? this.yieldReturn(enumerator.current())
1688 : this.yieldReturn(resultSelector(enumerator.current().key(), enumerator.current()));
1689 }
1690 return false;
1691 },
1692 function () { Utils.dispose(enumerator); });
1693 });
1694 };
1695
1696 // Overload:function(keySelector)
1697 // Overload:function(keySelector,elementSelector)
1698 // Overload:function(keySelector,elementSelector,resultSelector)
1699 // Overload:function(keySelector,elementSelector,resultSelector,compareSelector)
1700 Enumerable.prototype.partitionBy = function (keySelector, elementSelector, resultSelector, compareSelector) {
1701
1702 var source = this;
1703 keySelector = Utils.createLambda(keySelector);
1704 elementSelector = Utils.createLambda(elementSelector);
1705 compareSelector = Utils.createLambda(compareSelector);
1706 var hasResultSelector;
1707 if (resultSelector == null) {
1708 hasResultSelector = false;
1709 resultSelector = function (key, group) { return new Grouping(key, group); };
1710 }
1711 else {
1712 hasResultSelector = true;
1713 resultSelector = Utils.createLambda(resultSelector);
1714 }
1715
1716 return new Enumerable(function () {
1717 var enumerator;
1718 var key;
1719 var compareKey;
1720 var group = [];
1721
1722 return new IEnumerator(
1723 function () {
1724 enumerator = source.getEnumerator();
1725 if (enumerator.moveNext()) {
1726 key = keySelector(enumerator.current());
1727 compareKey = compareSelector(key);
1728 group.push(elementSelector(enumerator.current()));
1729 }
1730 },
1731 function () {
1732 var hasNext;
1733 while ((hasNext = enumerator.moveNext()) == true) {
1734 if (compareKey === compareSelector(keySelector(enumerator.current()))) {
1735 group.push(elementSelector(enumerator.current()));
1736 }
1737 else break;
1738 }
1739
1740 if (group.length > 0) {
1741 var result = (hasResultSelector)
1742 ? resultSelector(key, Enumerable.from(group))
1743 : resultSelector(key, group);
1744 if (hasNext) {
1745 key = keySelector(enumerator.current());
1746 compareKey = compareSelector(key);
1747 group = [elementSelector(enumerator.current())];
1748 }
1749 else group = [];
1750
1751 return this.yieldReturn(result);
1752 }
1753
1754 return false;
1755 },
1756 function () { Utils.dispose(enumerator); });
1757 });
1758 };
1759
1760 Enumerable.prototype.buffer = function (count) {
1761 var source = this;
1762
1763 return new Enumerable(function () {
1764 var enumerator;
1765
1766 return new IEnumerator(
1767 function () { enumerator = source.getEnumerator(); },
1768 function () {
1769 var array = [];
1770 var index = 0;
1771 while (enumerator.moveNext()) {
1772 array.push(enumerator.current());
1773 if (++index >= count) return this.yieldReturn(array);
1774 }
1775 if (array.length > 0) return this.yieldReturn(array);
1776 return false;
1777 },
1778 function () { Utils.dispose(enumerator); });
1779 });
1780 };
1781
1782 /* Aggregate Methods */
1783
1784 // Overload:function(func)
1785 // Overload:function(seed,func)
1786 // Overload:function(seed,func,resultSelector)
1787 Enumerable.prototype.aggregate = function (seed, func, resultSelector) {
1788 resultSelector = Utils.createLambda(resultSelector);
1789 return resultSelector(this.scan(seed, func, resultSelector).last());
1790 };
1791
1792 // Overload:function()
1793 // Overload:function(selector)
1794 Enumerable.prototype.average = function (selector) {
1795 selector = Utils.createLambda(selector);
1796
1797 var sum = 0;
1798 var count = 0;
1799 this.forEach(function (x) {
1800 sum += selector(x);
1801 ++count;
1802 });
1803
1804 return sum / count;
1805 };
1806
1807 // Overload:function()
1808 // Overload:function(predicate)
1809 Enumerable.prototype.count = function (predicate) {
1810 predicate = (predicate == null) ? Functions.True : Utils.createLambda(predicate);
1811
1812 var count = 0;
1813 this.forEach(function (x, i) {
1814 if (predicate(x, i))++count;
1815 });
1816 return count;
1817 };
1818
1819 // Overload:function()
1820 // Overload:function(selector)
1821 Enumerable.prototype.max = function (selector) {
1822 if (selector == null) selector = Functions.Identity;
1823 return this.select(selector).aggregate(function (a, b) { return (a > b) ? a : b; });
1824 };
1825
1826 // Overload:function()
1827 // Overload:function(selector)
1828 Enumerable.prototype.min = function (selector) {
1829 if (selector == null) selector = Functions.Identity;
1830 return this.select(selector).aggregate(function (a, b) { return (a < b) ? a : b; });
1831 };
1832
1833 Enumerable.prototype.maxBy = function (keySelector) {
1834 keySelector = Utils.createLambda(keySelector);
1835 return this.aggregate(function (a, b) { return (keySelector(a) > keySelector(b)) ? a : b; });
1836 };
1837
1838 Enumerable.prototype.minBy = function (keySelector) {
1839 keySelector = Utils.createLambda(keySelector);
1840 return this.aggregate(function (a, b) { return (keySelector(a) < keySelector(b)) ? a : b; });
1841 };
1842
1843 // Overload:function()
1844 // Overload:function(selector)
1845 Enumerable.prototype.sum = function (selector) {
1846 if (selector == null) selector = Functions.Identity;
1847 return this.select(selector).aggregate(0, function (a, b) { return a + b; });
1848 };
1849
1850 /* Paging Methods */
1851
1852 Enumerable.prototype.elementAt = function (index) {
1853 var value;
1854 var found = false;
1855 this.forEach(function (x, i) {
1856 if (i == index) {
1857 value = x;
1858 found = true;
1859 return false;
1860 }
1861 });
1862
1863 if (!found) throw new Error("index is less than 0 or greater than or equal to the number of elements in source.");
1864 return value;
1865 };
1866
1867 Enumerable.prototype.elementAtOrDefault = function (index, defaultValue) {
1868 if (defaultValue === undefined) defaultValue = null;
1869 var value;
1870 var found = false;
1871 this.forEach(function (x, i) {
1872 if (i == index) {
1873 value = x;
1874 found = true;
1875 return false;
1876 }
1877 });
1878
1879 return (!found) ? defaultValue : value;
1880 };
1881
1882 // Overload:function()
1883 // Overload:function(predicate)
1884 Enumerable.prototype.first = function (predicate) {
1885 if (predicate != null) return this.where(predicate).first();
1886
1887 var value;
1888 var found = false;
1889 this.forEach(function (x) {
1890 value = x;
1891 found = true;
1892 return false;
1893 });
1894
1895 if (!found) throw new Error("first:No element satisfies the condition.");
1896 return value;
1897 };
1898
1899 Enumerable.prototype.firstOrDefault = function (predicate, defaultValue) {
1900 if (predicate !== undefined) {
1901 if (typeof predicate === Types.Function || typeof Utils.createLambda(predicate) === Types.Function) {
1902 return this.where(predicate).firstOrDefault(undefined, defaultValue);
1903 }
1904 defaultValue = predicate;
1905 }
1906
1907 var value;
1908 var found = false;
1909 this.forEach(function (x) {
1910 value = x;
1911 found = true;
1912 return false;
1913 });
1914 return (!found) ? defaultValue : value;
1915 };
1916
1917 // Overload:function()
1918 // Overload:function(predicate)
1919 Enumerable.prototype.last = function (predicate) {
1920 if (predicate != null) return this.where(predicate).last();
1921
1922 var value;
1923 var found = false;
1924 this.forEach(function (x) {
1925 found = true;
1926 value = x;
1927 });
1928
1929 if (!found) throw new Error("last:No element satisfies the condition.");
1930 return value;
1931 };
1932
1933 Enumerable.prototype.lastOrDefault = function (predicate, defaultValue) {
1934 if (predicate !== undefined) {
1935 if (typeof predicate === Types.Function || typeof Utils.createLambda(predicate) === Types.Function) {
1936 return this.where(predicate).lastOrDefault(undefined, defaultValue);
1937 }
1938 defaultValue = predicate;
1939 }
1940
1941 var value;
1942 var found = false;
1943 this.forEach(function (x) {
1944 found = true;
1945 value = x;
1946 });
1947 return (!found) ? defaultValue : value;
1948 };
1949
1950 // Overload:function()
1951 // Overload:function(predicate)
1952 Enumerable.prototype.single = function (predicate) {
1953 if (predicate != null) return this.where(predicate).single();
1954
1955 var value;
1956 var found = false;
1957 this.forEach(function (x) {
1958 if (!found) {
1959 found = true;
1960 value = x;
1961 } else throw new Error("single:sequence contains more than one element.");
1962 });
1963
1964 if (!found) throw new Error("single:No element satisfies the condition.");
1965 return value;
1966 };
1967
1968 // Overload:function(defaultValue)
1969 // Overload:function(defaultValue,predicate)
1970 Enumerable.prototype.singleOrDefault = function (predicate, defaultValue) {
1971 if (defaultValue === undefined) defaultValue = null;
1972 if (predicate != null) return this.where(predicate).singleOrDefault(null, defaultValue);
1973
1974 var value;
1975 var found = false;
1976 this.forEach(function (x) {
1977 if (!found) {
1978 found = true;
1979 value = x;
1980 } else throw new Error("single:sequence contains more than one element.");
1981 });
1982
1983 return (!found) ? defaultValue : value;
1984 };
1985
1986 Enumerable.prototype.skip = function (count) {
1987 var source = this;
1988
1989 return new Enumerable(function () {
1990 var enumerator;
1991 var index = 0;
1992
1993 return new IEnumerator(
1994 function () {
1995 enumerator = source.getEnumerator();
1996 while (index++ < count && enumerator.moveNext()) {
1997 }
1998 ;
1999 },
2000 function () {
2001 return (enumerator.moveNext())
2002 ? this.yieldReturn(enumerator.current())
2003 : false;
2004 },
2005 function () { Utils.dispose(enumerator); });
2006 });
2007 };
2008
2009 // Overload:function(predicate)
2010 // Overload:function(predicate)
2011 Enumerable.prototype.skipWhile = function (predicate) {
2012 predicate = Utils.createLambda(predicate);
2013 var source = this;
2014
2015 return new Enumerable(function () {
2016 var enumerator;
2017 var index = 0;
2018 var isSkipEnd = false;
2019
2020 return new IEnumerator(
2021 function () { enumerator = source.getEnumerator(); },
2022 function () {
2023 while (!isSkipEnd) {
2024 if (enumerator.moveNext()) {
2025 if (!predicate(enumerator.current(), index++)) {
2026 isSkipEnd = true;
2027 return this.yieldReturn(enumerator.current());
2028 }
2029 continue;
2030 } else return false;
2031 }
2032
2033 return (enumerator.moveNext())
2034 ? this.yieldReturn(enumerator.current())
2035 : false;
2036
2037 },
2038 function () { Utils.dispose(enumerator); });
2039 });
2040 };
2041
2042 Enumerable.prototype.take = function (count) {
2043 var source = this;
2044
2045 return new Enumerable(function () {
2046 var enumerator;
2047 var index = 0;
2048
2049 return new IEnumerator(
2050 function () { enumerator = source.getEnumerator(); },
2051 function () {
2052 return (index++ < count && enumerator.moveNext())
2053 ? this.yieldReturn(enumerator.current())
2054 : false;
2055 },
2056 function () { Utils.dispose(enumerator); }
2057 );
2058 });
2059 };
2060
2061 // Overload:function(predicate)
2062 // Overload:function(predicate)
2063 Enumerable.prototype.takeWhile = function (predicate) {
2064 predicate = Utils.createLambda(predicate);
2065 var source = this;
2066
2067 return new Enumerable(function () {
2068 var enumerator;
2069 var index = 0;
2070
2071 return new IEnumerator(
2072 function () { enumerator = source.getEnumerator(); },
2073 function () {
2074 return (enumerator.moveNext() && predicate(enumerator.current(), index++))
2075 ? this.yieldReturn(enumerator.current())
2076 : false;
2077 },
2078 function () { Utils.dispose(enumerator); });
2079 });
2080 };
2081
2082 // Overload:function()
2083 // Overload:function(count)
2084 Enumerable.prototype.takeExceptLast = function (count) {
2085 if (count == null) count = 1;
2086 var source = this;
2087
2088 return new Enumerable(function () {
2089 if (count cell.Font.Bold == true)
47 .where(cell => cell.Borders.Item(xlEdgeTop)
48 .Weight == xlMedium)
49 .select(cell => cell.Address())
50 .toArray();
51 Console.log(headerCells.join(';'));
52 }
其输出如下:
$B$2;$C$2;$D$2;$E$2;$F$2;$G$2
因为宏编程其实就是在以编程的方式,对应用程序宿主公布给宏代码的对象以及集合打交道,操作无外乎增删改查。
有了 linq 这个库,我们就可以摆脱 var/for/if 这种散乱的拼凑的代码,而以 linq 的语义化的、直观的形式来编写我们想要的查询逻辑。
|